#include <jni.h>
#include <string>
#include <android/bitmap.h>
#include "commit.h"
#include "FFmpeg.h"

static const char *TAG = "NativeAPI";

extern "C" JNIEXPORT jstring JNICALL
Java_com_signway_ffmpeg_FFmpeg_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello:";
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "%X", avcodec_version());
    hello += buffer;

    const AVCodec *dec = nullptr;
    dec = avcodec_find_decoder(AV_CODEC_ID_H265);
    if (dec == nullptr) {
        LOGD("avcodec_find_decoder error");
    } else {
        LOGD("avcodec_find_decoder success %p", dec);
    }

    dec = avcodec_find_encoder(AV_CODEC_ID_H265);
    if (dec == nullptr) {
        LOGD("avcodec_find_encoder error");
    } else {
        LOGD("avcodec_find_encoder success %p", dec);
    }

    return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_signway_ffmpeg_FFmpeg_rotatingMediaFile(JNIEnv *env, jobject thiz, jstring src,
                                                 jstring dst, jint degree) {
    const char *srcFile = env->GetStringUTFChars(src, NULL);
    if (srcFile == nullptr) {
        LOGD("%d Failed to get utf-8 path from 'j_path'.", __LINE__);
    }

    const char *dstFile = env->GetStringUTFChars(dst, NULL);
    if (dstFile == nullptr) {
        LOGD("%d Failed to get utf-8 path from 'j_path'.", __LINE__);
    }

    LOGD("rotation media %s to %s degree:%d", srcFile, dstFile, degree);

    env->ReleaseStringUTFChars(dst, dstFile);
    env->ReleaseStringUTFChars(src, srcFile);
    return true;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_signway_ffmpeg_FFmpeg_nativeCreateEncoder(JNIEnv *env, jobject thiz, jint width,
                                                   jint height, jint fps, jint bitrate) {
    bool ret = createEncoder(width , height, fps, bitrate);
    return ret;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_signway_ffmpeg_FFmpeg_onOutputBufferAvailable(JNIEnv *env, jobject thiz,
                                                       jobject byte_buffer, jobject buffer_info) {
    int length = env->GetDirectBufferCapacity(byte_buffer);
    char *buffer = (char*) env->GetDirectBufferAddress(byte_buffer);

    jclass cls = env->GetObjectClass(buffer_info);

    jfieldID fid_flags = env->GetFieldID(cls, "flags", "I");
    jint flags = (jint) env->GetIntField(buffer_info, fid_flags);

    jfieldID fid_offset = env->GetFieldID(cls, "offset", "I");
    jint offset = (jint) env->GetIntField(buffer_info, fid_offset);

    jfieldID fid_pts = env->GetFieldID(cls, "presentationTimeUs", "J");
    jlong pts = (jint) env->GetLongField(buffer_info, fid_pts);

    jfieldID fid_size = env->GetFieldID(cls, "size", "I");
    jint size = (jint) env->GetIntField(buffer_info, fid_size);

    LOGD("length %d size %d offset %d pts %ld flag %d offset", length, size, offset, pts, flags);

    bool ret = onOutputBufferAvailable(buffer, length, pts, flags);

    return ret;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_signway_ffmpeg_FFmpeg_nativeCreateDecoder(JNIEnv *env, jobject thiz, jstring file) {
    const char *srcFile = env->GetStringUTFChars(file, NULL);
    if (srcFile == nullptr) {
        LOGD("%d Failed to get utf-8 path from 'j_path'.", __LINE__);
    }
    createDecoder(srcFile);
    env->ReleaseStringUTFChars(file, srcFile);
}